# http://www.toodledo.com/info/api_doc_tasks.php
# Initialization function
# TODO Decide where to put module comments. 
function Initialize
{
	# Set up module variables 	
}

<#
.SYNOPSIS
	Initializes the ToodleDo session and gets API key
.DESCRIPTION
	The Initialize-ToodleDo function gets the Token from ToodleDo and generates the API key to be used in further requests. 
.LINK
.EXAMPLE
	C:PS>Initialize-ToodleDo
	
	The Initialize-ToodleDo function gets the Token from ToodleDo and generates the API key to be used in further requests. 
.PARAMETER Email
	Email address for the user account
.PARAMETER Password
	Password for the user account
.PARAMETER AppID
	AppID is the ID that identifies the application being used.
.PARAMETER Output
	Whether to output the API Key. If this option is not set then the API key is stored in a script variable. 
#>
function Initialize-ToodleDo 
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Email
	,
	[parameter(Position=2,ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Password
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$AppID = "PowerShell"
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[switch]$Output
	)

	$Web = New-Object System.Net.WebClient

	if (!( ($Email) -and ($Password) ))
	{
		$Credential = $Host.UI.PromptForCredential("ToodleDo Login","Please enter your email address and password.","","") # In PS+ the message isn't being shown as specified. 
		$Email = $Credential.UserName -replace '\\',""
		$Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($($Credential.Password) ))
	}
	$UserIDURL = "http://www.toodledo.com/api.php?method=getUserid;email=$Email;pass=$Password"
	[xml]$Page = $Web.DownloadString($UserIDURL)

	if ( $Page.userid)
	{		$UserID = $Page.UserID }
	else
	{		Write-Error "No UserID returned" }

	$AuthenticationURL = "http://api.toodledo.com/api.php?method=getToken;userid=$UserID"
	if ($AppID )
	{		$AuthenticationURL += ";appid=$AppID" }

	[xml]$Page = $Web.DownloadString($AuthenticationURL)
	if ( $Page.error)
	{
		Write-Error $Page.Error
	}

	$Token = $Page.Token
	$EncryptedPassword = Get-MD5Hash($Password)
	$Key = Get-MD5Hash($EncryptedPassword + $Token + $Userid)

	if ($Output) 
	{		Write-Output $Key }
	else
	{		$Script:APIKey = $Key }
}

<#
.SYNOPSIS
	Gets ToodleDo account info.
.DESCRIPTION
	The Get-TDAccountInfo gets miscellaneous account information.  
.LINK
.EXAMPLE
	C:PS>Get-TDAccountInfo
	
	The Get-TDAccountInfo gets miscellaneous account information.  
#>
function Get-TDAccountInfo
{
	$Web = New-Object System.Net.WebClient

	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=getAccountInfo;key=$APIKey")
	$AccountInfo = New-Object PSObject -Property @{
		UserID = [string]$Document.account.userid
		Alias = [string]$Document.account.alias
		Pro = [bool] $Document.account.pro
		Dateformat = [int]$Document.account.dateformat
		Timezone = [int]$Document.account.timezone
		Hidemonths = [bool]$Document.account.hidemonths
		HotListPriorty = [int]$Document.account.hotlistpriority
		HotListDueDate = [int]$Document.account.hotlistduedate
		LastAddEdit = $Document.account.lastaddedit -as [datetime]
		LastDelete = $Document.account.lastdelete -as [datetime]
		LastFolderEdit = $Document.account.lastfolderedit -as [datetime]
		LastContextEdit = $Document.account.lastcontextedit -as [datetime]
		LastGoalEdit = $Document.account.lastgoaledit -as [datetime]
	} -ErrorAction "SilentlyContinue"

	$AccountInfo
}

<#
.SYNOPSIS
	Gets ToodleDo server info.
.DESCRIPTION
	The Get-TDServerInfo gets miscellaneous server information.  
.LINK
.EXAMPLE
	C:PS>Get-TDServerInfo
	
	The Get-TDServerInfo gets miscellaneous server information.  
#>
function Get-TDServerInfo
{
	$Web = New-Object System.Net.WebClient

	if ( ! ($ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=getServerInfo;key=$APIKey")
	$ServerInfo = New-Object PSObject -Property @{
		UnixTime = $Document.server.unixtime # Unix time at the server
		Date = [datetime]$Document.server.date # Date at the server
		ServerOffset = $Document.server.serveroffset
		TokenExpires = [system.datetime]::Now.AddMinutes($Document.server.tokenexpires) # When does the current token expire.
	}

	Write-Output $ServerInfo
}

<#
.SYNOPSIS
	Adds a new task to ToodleDo.
.DESCRIPTION
	This function adds a new task to your ToodleDo account. 
	
	The Add-TDTask allows you to add tasks to your ToodleDo account. If you haven't been previously authenticated then the function will authenticate you and add the task. Upon successful addition your task number will be returned. 
.LINK
	ToodleDo: http://www.toodledo.com
.EXAMPLE
.PARAMETER Title
	Sets the "title" or subject of the task to be added. 
.PARAMETER Tag
 	Sets the tag(s) for the task being added. Seperate tags with commas.
.PARAMETER Folder
	Sets the name of the folder the task is being added to. If the folder does not exist you will be prompted to create it. 
.PARAMETER Context
	Sets the name of the context the task is being added to. If the context does not exist you will be prompted to create it.
.PARAMETER Parent
	Sets the ID of the parent task. This will make this a subtask of that parent task. This feature is only available for pro accounts.
.PARAMETER DueDate
	Sets the date that the task is due.
.PARAMETER DueTime
	Sets the time that the task is due.
.PARAMETER StartDate
	Sets the date that the task will start.
.PARAMETER StartTime
	Sets the time that the task will start. 
.PARAMETER Reminder
	Sets the reminder in minutes to be reminded of the task. Possible values for this field are (0, 15, 30, 45, 60, 90, 120, 180, 240, 1440, 2880, 4320, 5760, 7200, 8640, 10080, 20160, 43200). 
	
	However if you do not have a pro account then any value you enter will be changed to 60.
.PARAMETER Status
	Sets the task to Status at the specified intervals. 
	
	Possible values are ("None", "Weekly", "Monthly", "Yearly", "Daily", "Biweekly", "Bimonthly", "Semiannually", "Quarterly", "Parent", "Advanced"). For advanced see the RepAdvanced paramter. 
.PARAMETER RepAdvanced
	Sets an advanced repeating interval. Accepts free-form text. 
.PARAMETER Status
	Sets the status of the task being added.
	
	Possible values are ("None","NextAction","Active","Planning","Delegated","Waiting","Hold","Postponed","Someday","Canceled","Reference").
.PARAMETER Length
	Sets the length in minutes that the task will take to complete. 
.PARAMETER Priority
	Sets the priority of the task
	
	Possible values are ("Negative","Low","Medium","High","Top")
.PARAMETER Star
	Sets whether the task will be stared
.PARAMETER Note
	Sets any notes that will be included with the task being added.
.NOTES
    
  ** Licensed under a Creative Commons Attribution 3.0 License ** 
#>
function Add-TDTask
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$True,Mandatory=$True)]
	[ValidateNotNullOrEmpty()]
	[string]$Title
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateLength(1,36)]
	[string]$Tag
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Folder
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Context
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Parent
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$DueDate
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$StartDate
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$DueTime
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$StartTime
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet(0, 15, 30, 45, 60, 90, 120, 180, 240, 1440, 2880, 4320, 5760, 7200, 8640, 10080, 20160, 43200)]
	[int]$Reminder
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("None", "Weekly", "Monthly", "Yearly", "Daily", "Biweekly", "Bimonthly", "Semiannually", "Quarterly", "Parent", "Advanced")]
	[string]$Repeat
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$RepAdvanced
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("None","NextAction","Active","Planning","Delegated","Waiting","Hold","Postponed","Someday","Canceled","Reference")]
	[string]$Status
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Length
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("Negative","Low","Medium","High","Top")]
	[int]$Priority
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[switch]$Star
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Note 

	)

	$Web = New-Object System.Net.WebClient

	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	$ApiKey = $Script:ApiKey

	$TaskAddURL = "Http://api.toodledo.com/api.php?method=addTask;key=$ApiKey;title=$Title"

	#region Tag Section
	if ($Tag) 
	{
		#Please encode the & character as %26 and the ; character as %3B.
		$Tag = $Tag -replace '&', '%26'
		$Tag = $Tag -replace ';', '%3B'
		$TaskAddURL += ";tag=$Tag"
	}
	#endregion

	if ($Folder)
	{
		$FolderExists = $False
		Get-TDFolders | 
		% { 
			if( $_.Text -match $Folder )
			{
				$FolderExists = $True
			}
		}

		if ( ! $FolderExists)
		{
			$CreateFolder = Read-Host "$Folder is not a current folder. Do you want to create? (y/n)"
			if ( $CreateFolder -eq 'y')
			{
				Add-TDFolder -Name $Folder
			} # if ( $CreateFolder -eq 'y')
		} # if ( ! $FolderExists)

		$FolderID = (Get-TDFolders $Folder | Select-Object ID).ID
		$TaskAddURL += ";folder=$FolderID"

	} # EndIf ($Folder)

	if ($Context)
	{
		$ContextExists = $False
		Get-TDContexts | 
		% { 
			if( $_.Text -match $Context )
			{				$ContextExists = $True }
		}

		if ( ! $ContextExists)
		{
			$CreateContext = Read-Host "$Context is not a current context. Do you want to create? (y/n)"
			if ( $CreateContext -eq 'y')
			{				Add-TDContext -Name $Context } # if ( $CreateContext -eq 'y')
		} # if ( ! $ContextExists)
		$ContextID = (Get-TDContexts $Context | Select-Object ID).ID
		$TaskAddURL += ";context=$ContextID"
	} # EndIf ($Context)

# Parent 
	if ($Parent)
	{		$TaskAddURL += ";parent=$Parent" }

	# Due Date
	if ($DueDate)
	{		$TaskAddUrl += ";duedate=$($DueDate.ToString('yyyy-MM-dd'))" }

	# Due Time
	if ($DueTime)
	{		$TaskAddURL += ";duetime=$($DueTime.ToString('HH:mm tt'))" }

	# Start Date
	if ($StartDate)
	{		$TaskAddUrl += ";startdate=$($StartDate.ToString('yyyy-MM-dd'))" }

	# Start Time
	if ($StartTime)
	{		$TaskAddURL += ";starttime=$($StartTime.ToString('HH:mm tt'))" }

	# Reminder
# TODO Verify based on Pro account or not
	if ($Reminder) 
	{		$TaskAddURL += ";reminder=$Reminder" }

	# Repeat
	if ($Repeat)
	{
		switch ($Repeat)
		{
			"None" { $RepeatID = 0 }
			"Weekly"{ $RepeatID = 1 }
			"Monthly"{ $RepeatID = 2 }
			"Yearly"{ $RepeatID = 3 }
			"Daily"{ $RepeatID = 4 }
			"Biweekly"{ $RepeatID = 5 }
			"Bimonthly"{ $RepeatID = 6 }
			"Semiannually"{ $RepeatID = 7 }
			"Quarterly"{ $RepeatID = 8 }
			"Parent"{ $RepeatID = 9 }
			"Advanced"{ $RepeatID = 50; } 
		}
		$TaskAddURL += ";repeat=$RepeatID"
	}

	if (($RepAdvanced) -and ($Repeat -eq 50) )
	{		$TaskAddURL += ";rep_advanced=$RepAdvanced" }

	# Status
	if ($Status)
	{
		switch ($Status)
		{
			"None" {$StatusID = 0 }
			"NextAction" {$StatusID = 1 }
			"Active" {$StatusID = 2 }
			"Planning" {$StatusID = 3 }
			"Delegated" {$StatusID = 4 }
			"Waiting" {$StatusID = 5 }
			"Hold" {$StatusID = 6 }
			"Postponed" {$StatusID = 7 }
			"Someday" {$StatusID = 8 }
			"Canceled" {$StatusID = 9 }
			"Reference" {$StatusID = 10 }
		}
		$TaskAddURL += ";status=$StatusID"
	}

	if ($Length)
	{		$TaskAddURL += ";length=$Length"} 

	# Priority
	if ($Priority )
	{
		switch ($Priority) 
		{
			"Negative" { $PriorityID = -1 }
			"Low"{ $PriorityID = 0 }
			"Medium"{ $PriorityID = 1 }
			"High"{ $PriorityID = 2 }
			"Top"{ $PriorityID = 3 }
		}
		$TaskAddURL += ";priority=$PriorityID" 
	}

	# Star
	if ($Star )
	{		$TaskAddURL += ";star=1" }

	#Note
	if ($Note)
	{
		$Note = $Note -replace '&', '%26'
		$Note = $Note -replace ';', '%3B'
		$TaskAddURL += ";note=$Note"
	}

	#Write-Debug $($TaskAddURL)
	[xml]$Document = $Web.DownloadString($TaskAddURL)
	$ID = $Document.added | add-member ToString -type scriptmethod { "Item has been added with ID: $this" } -force -passthru
	return $ID

}

<#
.SYNOPSIS
	Gets the list of ToodleDo folders
.DESCRIPTION
	The Get-TDFolders function retrieves the folders.
.LINK
.EXAMPLE
	C:PS>Get-TDFolders
	
	This command retrieves the ToodleDo folders configured in the user's account.
.EXAMPLE
	C:PS>Get-TDFolders -Name "Testing"
	
	This command retrieves the ToodleDO folders configured in the user's account whose name is "Testing".
.PARAMETER Name
	The name of the folder to be retrieved.
.PARAMETER ID
	The id of the folder to be retrieved.
#>
function Get-TDFolders
{
	[CmdletBinding(DefaultParameterSetName="Name",SupportsShouldProcess=$False)]
	param
	(
	[parameter(ParameterSetName="ID",Position=1,ValueFromPipeline=$True,Mandatory=$False)]
	[int]$FolderID 
	,
	[parameter(ParameterSetName="Name",Position=1,ValueFromPipeline=$True,Mandatory=$False)]
	[string]$FolderName 
	)
	$Web = New-Object System.Net.WebClient

	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=getFolders;key=$APIKey")
	if ( $Document.error -eq 'key did not validate' )
	{		Write-Error "Key did not validate" }
	else
	{
		$Folders = @()
		foreach ($FolderXML in $Document.folders.Folder )
		{
			$Folder = New-Object PSObject -Property @{
				ID = [int]$FolderXML.ID
				Private = [bool]$FolderXML.Private
				Archived = [bool]$FolderXML.Archived
				Order = [int]$FolderXML.Order
				Text = [string]$FolderXML.InnerText
			}
			$Folders += $Folder
		}
		if ($FolderName )
		{
			$folders | Where-Object { $_.Text -eq "$FolderName" } 
		}
		elseif ( $FolderID )
		{
			$Folders | Where-Object { $_.ID -eq $FolderID }
		}
		else
		{
			Write-Output $Folders 
		}

	}
}
<#
.SYNOPSIS
	Gets a task(s) from ToodleDo.
.DESCRIPTION
	This function Gets task(s) from your ToodleDo account. 
	
	The Get-TDTask allows you from Get tasks from your ToodleDo account. If you haven't been previously authenticated then the function will authenticate you and Get the task(s). 
.LINK
	ToodleDo: http://www.ToodleDo.com
.EXAMPLE
.PARAMETER Title
	A text string up to 255 characters. Boolean operators do not work yet, so your search will be for a single phrase. 
.PARAMETER Tag
 	Specifies one or more tasks by tags. Seperate tags with commas. 
.PARAMETER Folder
	Specifies one or more tasks by folder. 
.PARAMETER Context
	Specifies one or more tasks by context.
.PARAMETER Goal
	Specifies one or more tasks by goal.
.PARAMETER Priority
	Specifies one or more tasks by priority
	
	Possible values are ("Negative","Low","Medium","High","Top")
.PARAMETER Repeat
	Specifies one or more tasks by how often they repeat at the specified intervals. 
	
	Possible values are ("None", "Weekly", "Monthly", "Yearly", "Daily", "Biweekly", "Bimonthly", "Semiannually", "Quarterly", "Parent").
.PARAMETER Status
	Sets the status of the task being retrieved.
	
	Possible values are ("None","NextAction","Active","Planning","Delegated","Waiting","Hold","Postponed","Someday","Canceled","Reference").
.PARAMETER Parent
	Specifies one or more tasks by the ID of the parent task. This is used to Pro accounts that have access to subtasks. Set this to the id number of the parent task and you will get its subtasks. The default is 0, which is a special number that returns tasks that do not have a parent.
.PARAMETER shorter
	Specifies one or more tasks with a duration shorter than the value specified.
.PARAMETER longer
	Specifies one or more tasks with a duration longer than the value specified.
.PARAMETER before
	Specifies one or more tasks due before date specified.
.PARAMETER after
	Specifies one or more tasks due after date specified. 
.PARAMETER startbefore
	Specifies one or more tasks starting before date specified.
.PARAMETER startafter
	Specifies one or more tasks starting after date specified. 
.PARAMETER modbefore
	Specifies one or more tasks modified before date specified.
.PARAMETER modafter
	Specifies one or more tasks modified after date specified. 
.PARAMETER compbefore
	Specifies one or more tasks completed before date specified.
.PARAMETER compafter
	Specifies one or more tasks completed after date specified. 
.PARAMETER Completed
	Sets whether to include completed tasks.
.PARAMETER Star
	Specifies one or more tasks that are stared	
.PARAMETER ID
	Retrieves the task with the specified ID.
  ** Licensed under a Creative Commons Attribution 3.0 License ** 
#>
function Get-TDTask
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$True,Mandatory=$False)]
	[string]
	[ValidateLength(1,255)]
	$Title
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]
	[ValidateLength(1,64)]
	$Tag
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Folder
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[string]$Context
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Goal
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("Negative","Low","Medium","High","fromp")]
	[int]$Priority
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("None", "Weekly", "Monthly", "Yearly", "Daily", "Biweekly", "Bimonthly", "Semiannually", "Quarterly", "Parent", "Advanced")]
	[string]$Repeat
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[ValidateSet("None","NextAction","Active","Planning","Delegated","Waiting","Hold","Postponed","Someday","Canceled","Reference")]
	[string]$Status
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Parent
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Shorter
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$Longer
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$Before
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$After
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$StartBefore
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$StartAfter
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$ModBefore
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$ModAfter
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$CompBefore
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[datetime]$CompAfter
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[switch]$Completed
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[switch]$Star
	,
	[parameter(ValueFromPipeline=$False,Mandatory=$False)]
	[int]$ID
	)
	begin{

		$Web = New-Object System.Net.WebClient

		if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
		{			Initialize-ToodleDo }

		$ApiKey = $Script:ApiKey

		$TaskGetURL = "Http://api.ToodleDo.com/api.php?method=getTasks;key=$ApiKey"

		if ($Title) 
		{
			#Please encode the & character as %26 and the ; character as %3B.
			$Title = $Title -replace '&', '%26'
			$Title = $Title -replace ';', '%3B'
			$TaskGetURL += ";title=$Title"
		}

		if ($Tag) 
		{
			#Please encode the & character as %26 and the ; character as %3B.
			$Tag = $Tag -replace '&', '%26'
			$Tag = $Tag -replace ';', '%3B'
			$TaskGetURL += ";tag=$Tag"
		}

		if ($Folder)
		{
			$FolderExists = $False
			Get-TDFolders | 
			% { 
				if( $_.Text -match $Folder )
				{
					$FolderExists = $True
				}
			}

			if ( ! $FolderExists)
			{
				Write-Error "Folder specified does not exist"
			} 
			else # if ( ! $FolderExists)
			{
				$FolderID = (Get-TDFolders $Folder | Select-Object ID).ID
				$TaskGetURL += ";folder=$FolderID"
			} # if ( ! $FolderExists)
		} # EndIf ($Folder)

		if ($Context)
		{
			$ContextExists = $False
			Get-TDContexts | 
			% { 
				if( $_.Text -match $Context )
				{					$ContextExists = $True }
			}

			if ( ! $ContextExists)
			{
				Write-Error "Context specified does not exist"
			}
			else # if ( ! $ContextExists)
			{
				$ContextID = (Get-TDContexts $Context | Select-Object ID).ID
				$TaskGetURL += ";context=$ContextID"
			} # if ( ! $ContextExists)
		} # EndIf ($Context)

		if ($Goal)
		{			$TaskGetURL += ";goal=$Goal" }

		if ($Priority )
		{
			switch ($Priority) 
			{
				"Negative" { $PriorityID = -1 }
				"Low"{ $PriorityID = 0 }
				"Medium"{ $PriorityID = 1 }
				"High"{ $PriorityID = 2 }
				"fromp"{ $PriorityID = 3 }
			}
			$TaskGetURL += ";priority=$PriorityID" 
		}

		if ($Repeat)
		{
			switch ($Repeat)
			{
				"None" { $RepeatID = 0 }
				"Weekly"{ $RepeatID = 1 }
				"Monthly"{ $RepeatID = 2 }
				"Yearly"{ $RepeatID = 3 }
				"Daily"{ $RepeatID = 4 }
				"Biweekly"{ $RepeatID = 5 }
				"Bimonthly"{ $RepeatID = 6 }
				"Semiannually"{ $RepeatID = 7 }
				"Quarterly"{ $RepeatID = 8 }
				"Parent"{ $RepeatID = 9 }
				"Advanced"{ $RepeatID = 50; } 
			}
			$TaskGetURL += ";repeat=$RepeatID"
		}

		if ($Status)
		{
			switch ($Status)
			{
				"None" {$StatusID = 0 }
				"NextAction" {$StatusID = 1 }
				"Active" {$StatusID = 2 }
				"Planning" {$StatusID = 3 }
				"Delegated" {$StatusID = 4 }
				"Waiting" {$StatusID = 5 }
				"Hold" {$StatusID = 6 }
				"Postponed" {$StatusID = 7 }
				"Someday" {$StatusID = 8 }
				"Canceled" {$StatusID = 9 }
				"Reference" {$StatusID = 10 }
			}
			$TaskGetURL += ";status=$StatusID"
		}

		if ($Shorter)
		{			$TaskGetURL += ";shorter=$Shorter" }

		if ($Longer)
		{			$TaskGetURL += ";longer=$Longer" }

		if ($Before)
		{			$TaskGetUrl += ";before=$($Before.ToString('yyyy-MM-dd'))" }

		if ($After)
		{			$TaskGetUrl += ";after=$($After.ToString('yyyy-MM-dd'))" }

		if ($StartBefore)
		{			$TaskGetUrl += ";startbefore=$($StartBefore.ToString('yyyy-MM-dd'))" }

		if ($StartAfter)
		{			$TaskGetUrl += ";startafter=$($startAfter.ToString('yyyy-MM-dd'))" }

		if ($ModBefore)
		{			$TaskGetUrl += ";modbefore=$($ModBefore.ToString('yyyy-MM-dd HH:mm'))" }

		if ($ModAfter)
		{			$TaskGetUrl += ";modafter=$($ModAfter.ToString('yyyy-MM-dd HH:mm'))" }

		if ($CompBefore)
		{			$TaskGetUrl += ";compbefore=$($CompBefore.ToString('yyyy-MM-dd'))" }

		if ($CompAfter)
		{			$TaskGetUrl += ";compafter=$($CompAfter.ToString('yyyy-MM-dd'))" }

		if ($Parent)
		{			$TaskGetURL += ";parent=$Parent" }

		if ($Completed )
		{			$TaskGetURL += ";notcomp=0" }
		else
		{			$TaskGetURL += ";notcomp=1" }

		if ($Star )
		{			$TaskGetURL += ";star=1" }

		if ($ID)
		{
			$TaskGetURL += ";id=$ID"
		}

		[xml]$Document = $Web.DownloadString($TaskGetURL)
	}
	process
	{
		foreach ($ContextXML in $Document.Tasks.Task )
		{
			$myTask = New-Object PSObject -Property @{
				ID = [int]$ContextXML.ID
				Parent = [int]$ContextXML.Parent
				Children = [int]$ContextXML.Children
				Title = [string]$ContextXML.Title
				Tag = [string]$ContextXML.Tag # Need to split these out into indivdual tags
				Folder = [string](Get-TDFolders -FolderID $ContextXML.folder | Select-Object Text).Text
				Context = [string](Get-TDContexts -ContextID $ContextXML.folder | Select-Object Text).Text
				Goal = [int]$ContextXML.Goal.ID
				Added = $ContextXML.Added -as [datetime]
				Modified = $ContextXML.modified -as [datetime]
				StartDate =$ContextXML.startdate -as [datetime]
				DueDate = $ContextXML.duedate.innertext -as [datetime]
				#<duedate modifier=""/>
				DueTime = $ContextXML.duetime -as [datetime]
				StartTime = $ContextXML.starttime -as [datetime]
				Reminder = [int]$ContextXML.reminder 
				Completed = [bool]$ContextXML.completed
				Repeat = [string]$ContextXML.Repeat
				Status = [string]$ContextXML.Status
				Star = [bool]$ContextXML.Star
				Priority = [int]$ContextXML.Priority
				Length = [int]$ContextXML.length
				Note = [string]$ContextXML.Note
			}

			switch ($myTask.Repeat)
			{
				"0" { $myTask.Repeat = "None"}
				"1" { $myTask.Repeat = "Weekly" }
				"2" { $myTask.Repeat = "Monthly" }
				"3" { $myTask.Repeat = "Yearly" }
				"4" { $myTask.Repeat = "Daily" }
				"5" { $myTask.Repeat = "Biweekly" }
				"6" { $myTask.Repeat = "Bimonthly" }
				"7" { $myTask.Repeat = "Semiannually" }
				"8" { $myTask.Repeat = "Quarterly" }
				"9" { $myTask.Repeat = "Parent" }
			} 

			switch ($myTask.Status)
			{
				"0" { $myTask.Status = "None"}
				"1" { $myTask.Status = "NextAction" }
				"2" { $myTask.Status = "Active" }
				"3" { $myTask.Status = "Planning" }
				"4" { $myTask.Status = "Delegated" }
				"5" { $myTask.Status = "Waiting" }
				"6" { $myTask.Status = "Hold" }
				"7" { $myTask.Status = "Postponed" }
				"8" { $myTask.Status = "Someday" }
				"9" { $myTask.Status = "Canceled" }
				"9" { $myTask.Status = "Reference" }
			} 

			#$Task = New-Object PSObject -Property $myTask
			$myTask.PSTypeNames.Clear()
			$myTask.PSTypeNames.Add('ToodlePosh.Tasks')
			$myTask
		}


	}
}

<#
.SYNOPSIS
 Adds a ToodleDo Context
.DESCRIPTION
	The Add-TDContext function adds a context.
.LINK
.EXAMPLE
	C:PS>Add-TDContext Context 
	
	This command adds a context called "Context".
.PARAMETER Name
	The title of the context to be added.

#>
function Add-TDContext
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$True,Mandatory=$True)]
	[string]
	[ValidateLength(1,32)]
	$Name
	)

	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	$Web = New-Object System.Net.WebClient

	# Check for existing context name even though the system will allow it. 
	$ContextExists = $False
	Get-TDContexts | 
	% { 
		if( $_.Text -match $Name )
		{			$ContextExists = $True }
	}

	if ( ! $ContextExists)
	{
		[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=addContext;key=$Script:ApiKey;title=$Name")
		if ( $Document.error -eq 'key did not validate' )
		{			Write-Error "Key did not validate" }
		if ( $Document.added ) 
		{
			Write-Host "Context `"$Name`" was added with ID $($Document.added)" -ForegroundColor Green
		}
	} 
	else # if ( ! $ContextExists)
	{		Write-Host "Context `"$Name`" already exists." -ForegroundColor Yellow } # if ( ! $ContextExists)
}
<#
.SYNOPSIS
 Adds a ToodleDo Folder
.DESCRIPTION
	The Add-TDFolder function adds a folders.
.LINK
.EXAMPLE
	C:PS>Add-TDFolder Folder $True
	
	This command adds a private folder called "Folder.
.PARAMETER Name
	The title of the folder to be added.
.PARAMETER Private
	Indicates whether the folder should be private.
#>
function Add-TDFolder
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$True,Mandatory=$True)]
	[string]
	[ValidateLength(1,32)]
	$Name
	,
	[parameter(Position=2,ValueFromPipeline=$False,Mandatory=$False)]
	[switch]$Private
	)

	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	$Web = New-Object System.Net.WebClient

	if ($Private)
	{		$PrivateFolder = 1}
	else
	{		$PrivateFolder = 0}

	# Check for existing folder name even though the system will allow it. 
	$FolderExists = $False
	Get-TDFolders
	$Script:Folders | 
	% { 
		if( $_.Text -match $Name )
		{			$FolderExists = $True }
	}

	if ( ! $FolderExists)
	{
		[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=addFolder;key=$Script:ApiKey;title=$Name;private=$PrivateFolder")
		if ( $Document.error -eq 'key did not validate' )
		{			Write-Error "Key did not validate" }
		if ( $Document.added ) 
		{
			Write-Host "Folder `"$Name`" was added with ID $($Document.added)" -ForegroundColor Green
			Get-TDFolders # Refresh folder list
		}
	} 
	else # if ( ! $FolderExists)
	{		Write-Host "Folder `"$Name`" already exists." -ForegroundColor Yellow } # if ( ! $FolderExists)
}
<#
.SYNOPSIS
	Gets the list of ToodleDo context
.DESCRIPTION
	The Get-TDContexts function retrieves the contexts.
.LINK
.EXAMPLE
	C:PS>Get-TDContexts
	
	This command retrieves the ToodleDo contexts configured in the user's account.
.EXAMPLE
	C:PS>Get-TDContexts
	
	This command retrieves the ToodleDO contexts configured in the user's account.
.PARAMETER Name
	The name of the context to be retrieved.
.PARAMETER ID
	The id of the context to be retrieved.
#>
function Get-TDContexts
{
	[CmdletBinding(DefaultParameterSetName="Name",SupportsShouldProcess=$False)]
	param
	(
	[parameter(ParameterSetName="ID",Position=1,ValueFromPipeline=$True,Mandatory=$False)]
	[int]$ContextID 
	,
	[parameter(ParameterSetName="Name",Position=1,ValueFromPipeline=$True,Mandatory=$False)]
	[string]$ContextName 
	)
	if ( ! ($Script:ApiKey) ) # Make sure APIKey is stored.
	{		Initialize-ToodleDo }

	$Web = New-Object System.Net.WebClient
	[xml]$Document = $Web.DownloadString("http://api.toodledo.com/api.php?method=getContexts;key=$APIKey")
	if ( $Document.error -eq 'key did not validate' )
	{		Write-Error "Key did not validate" }
	else
	{
		$Contexts = @()
		foreach ($ContextXML in $Document.Contexts.Context )
		{
			$Context = New-Object PSObject -Property @{
				ID = [int]$ContextXML.ID
				Text = [string]$ContextXML.InnerText
			}
			$Contexts += $Context
		}
		if ($ContextName )
		{
			$Contexts | Where-Object { $_.Text -eq "$ContextName" } 
		}
		elseif ( $ContextID )
		{
			$Contexts | Where-Object { $_.ID -eq $ContextID }
		}
		else
		{
			Write-Output $Contexts
		}
		$Script:Contexts = $Contexts
	}

}

<#
.SYNOPSIS
	Calculates the MD5 hash of a input value
.DESCRIPTION
	The Get-MD5Hash function calculates the MD5 hash of a string input
.PARAMETER Text
	Text is the string that you want to get the MD5 hash for.
#>
function Get-MD5Hash
{
	[CmdletBinding(SupportsShouldProcess=$False)]
	param
	(
	[parameter(Position=1,ValueFromPipeline=$True,Mandatory=$True)]
	[string]$Text
	)
	$Result = ""
	[byte[]]$OriginalBytes = [System.Text.Encoding]::ASCII.GetBytes($Text)
	[byte[]]$EncodedBytes = (New-Object System.Security.Cryptography.MD5CryptoServiceProvider).ComputeHash($OriginalBytes)
	0..($EncodedBytes.Length - 1) | % { $Result += $EncodedBytes[$_].ToString("x2") }
	Write-Output $Result
}

Initialize
